package codechicken.wirelessredstone.core;

import net.minecraft.src.*;

public class WRVector3
{
	public WRVector3(double x, double y, double z)
	{
		this.x = (float) x;
		this.y = (float) y;
		this.z = (float) z;
	}
	
	public WRVector3(BlockCoord node)
	{
		this(node.x + 0.5, node.y + 0.5, node.z + 0.5);
	}

	public WRVector3(TileEntity tile)
	{
		if(tile instanceof ITileWireless)
		{
			WRVector3 point = ((ITileWireless)tile).getFocalPoint();
			x = (float) point.x + tile.xCoord + 0.5F;
			y = (float) point.y + tile.yCoord + 0.5F;
			z = (float) point.z + tile.zCoord + 0.5F;
		}
		else if(tile instanceof ITileJammer)
		{
			WRVector3 point = ((ITileJammer)tile).getFocalPoint();
			x = (float) point.x + tile.xCoord + 0.5F;
			y = (float) point.y + tile.yCoord + 0.5F;
			z = (float) point.z + tile.zCoord + 0.5F;
		}
		else
		{
			x = tile.xCoord + 0.5F;
			y = tile.yCoord + 0.5F;
			z = tile.zCoord + 0.5F;
		}
	}

	public WRVector3(Entity entity)
	{
		this(entity.posX, entity.posY, entity.posZ);
	}

	public WRVector3 add(WRVector3 vec)
	{
		x+=vec.x;
		y+=vec.y;
		z+=vec.z;
		return this;
	}
	
	public WRVector3 sub(WRVector3 vec)
	{
		x-=vec.x;
		y-=vec.y;
		z-=vec.z;
		return this;
	}
	
	public WRVector3 scale(float scale)
	{
		x*=scale;
		y*=scale;
		z*=scale;
		return this;
	}
	
	public WRVector3 scale(float scalex, float scaley, float scalez)
	{
		x*=scalex;
		y*=scaley;
		z*=scalez;
		return this;
	}
	
	public WRVector3 normalize()
	{
		float length = length();
		x/=length;
		y/=length;
		z/=length;
		return this;
	}
	
	public float length()
	{
		return (float) Math.sqrt(x*x+y*y+z*z);
	}
	
	public float lengthPow2()
	{
		return x*x+y*y+z*z;
	}

	public WRVector3 copy()
	{
		return new WRVector3(x, y, z);
	}
	
	public static WRVector3 crossProduct(WRVector3 vec1, WRVector3 vec2)
	{
		return new WRVector3(
				vec1.y*vec2.z - vec1.z*vec2.y,
				vec1.z*vec2.x - vec1.x*vec2.z,
				vec1.x*vec2.y - vec1.y*vec2.x);		
	}
	
	public static WRVector3 xCrossProduct(WRVector3 vec)
	{
		return new WRVector3(0, vec.z, -vec.y);
	}
	
	public static WRVector3 zCrossProduct(WRVector3 vec)
	{
		return new WRVector3(-vec.y, vec.x, 0);
	}
	
	public static float dotProduct(WRVector3 vec1, WRVector3 vec2)
	{
		return vec1.x*vec2.x + vec1.y*vec2.y + vec1.z*vec2.z;
	}
	
	public static float angle(WRVector3 vec1, WRVector3 vec2)
	{
		return anglePreNorm(vec1.copy().normalize(), vec2.copy().normalize());
	}
	
	public static float anglePreNorm(WRVector3 vec1, WRVector3 vec2)
	{
		return (float) Math.acos(dotProduct(vec1, vec2));
	}
	
	public WRVector3 rotate(float angle, WRVector3 axis)
	{
		return WRMat4.rotationMat(angle, axis).translate(this);
	}
	
	public String toString()
	{
		return "["+x+","+y+","+z+"]";
	}
	
	public float x, y, z;

	public Vec3D toVec3D()
	{
		return Vec3D.createVector(x, y, z);
	}

	public static WRVector3 getPerpendicular(WRVector3 vec)
	{
		if(vec.z == 0)
		{
			return zCrossProduct(vec);
		}
		else
		{
			return xCrossProduct(vec);
		}
	}

	public BlockCoord toCoord()
	{
		return new BlockCoord((int)x, (int)y, (int)z);
	}

	public boolean isZero()
	{
		return x == 0 && y == 0 && z == 0;
	}
}
